
/*
 * Copyright (C) 2008-2009 Archie L. Cobbs. All rights reserved.
 *
 * $Id: Item.java 380 2010-03-11 22:27:58Z archie.cobbs $
 */

package org.dellroad.sidekar;

/**
 * Interface implemented by all Sidekar runtime data objects.
 * Instances of this class directly represent some area of storage in the database.
 *
 * <p>
 * At runtime, Sidekar creates subclasses of the user model classes given to it. These subclasses
 * override the accessor methods for all defined Sidekar fields and also add the methods below to
 * implement this interface. Abstract user model classes may also implement this interface explicitly;
 * this elminates the need to cast data objects to {@code Item} in order to access these methods.
 * </p>
 *
 * <p>
 * An instance of this interface may exist even though the corresponding area of storage has been
 * deleted from the database; such instances are called "detached". In this case, attempting to
 * access any Sidekar fields will generate a {@link DetachedItemException}. Detached instances
 * may be reattached, though all fields will be reset to their default values.
 * The {@link #sidekarAttach} and {@link #sidekarDetach} methods change an item's "attached" status.
 * </p>
 *
 * <p>
 * This interface implicitly defines the following Java bean properties and reflection field types:
 * <ul>
 * <li>{@code sidekarEntity} - also defined as {@link Sidekar#ENTITY_FIELD_NAME} - reflected via {@link EntityField}</li>
 * <li>{@code sidekarId} - also defined as {@link Sidekar#ID_FIELD_NAME} - reflected via {@link IdField}</li>
 * <li>{@code sidekarAttached} - also defined as {@link Sidekar#ATTACHED_FIELD_NAME} - reflected via {@link AttachedField}</li>
 * </ul>
 * </p>
 *
 * @param <T> associated user model class
 * @see ImplicitField
 */
public interface Item<T> {

    /**
     * Get the unique instance id for this item.
     *
     * <p>
     * Item id's are unique among all instances of a specific {@link Entity}.
     * However, items of different entity types (even in the same type hierarchy) can have the same id.
     *
     * <p>
     * This method always succeeds, even if this instance is detached.
     *
     * @return this item's unique id, always positive
     * @see Entity#get(long) Entity.get()
     */
    long getSidekarId();

    /**
     * Get the {@link Entity} of which this item is an instance.
     *
     * <p>
     * This method always succeeds, even if this instance is detached.
     *
     * @return this item's associated {@link Entity}
     */
    Entity<T> getSidekarEntity();

    /**
     * Attach this item to the database.
     *
     * <p>
     * If this item was previously detached, space will be allocated in the database
     * and all fields will be reset to their default values.
     * This method does nothing if the item is already attached.
     * </p>
     *
     * <p>
     * Once attached, an item will remain in the database until it is detached.
     * </p>
     *
     * @throws IllegalStateException if the database containing this item has been closed
     * @see #sidekarDetach
     */
    void sidekarAttach();

    /**
     * Detach this item from the database.
     *
     * <p>
     * If this item was previously attached, it will be removed from the database and the
     * contents of all Sidekar fields will be lost.
     * This method does nothing if the item is already detached.
     * </p>
     *
     * @throws IllegalStateException if the database containing this item has been closed
     * @see #sidekarAttach
     */
    void sidekarDetach();

    /**
     * Determine if this item is attached.
     *
     * @see #sidekarAttach
     * @see #sidekarDetach
     * @throws IllegalStateException if the database containing this item has been closed
     */
    boolean isSidekarAttached();

    /**
     * Validate this item. This method verifies that this instance still exists in the database,
     * i.e., it has not been deleted. If so, this instance is returned; if not, an exception is thrown.
     *
     * @return this instance
     * @throws DetachedItemException if this item is detached
     * @throws IllegalStateException if the database containing this item has been closed
     */
    Item<T> sidekarValidate();
}

